package com.whty.demo.repo;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import com.whty.demo.encrypt.EncryptUtil;
import com.whty.demo.encrypt.ReflectUtil;
import com.whty.demo.util.UUIDUtil;

/**
 * @ClassName BaseRepositoryImpl
 * @author Administrator
 * @date 2017-4-20 下午4:04:55
 * @Description TODO(这里用一句话描述这个类的作用)
 */
public class BaseRepositoryImpl<T, ID extends Serializable> extends
		SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
	
	@SuppressWarnings("unused")
	private Logger logger = LoggerFactory.getLogger(BaseRepositoryImpl.class);

	private final Class<T> domainClass;
	private final EntityManager entityManager;  

	// 父类没有不带参数的构造方法，这里手动构造父类
	public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
		super(domainClass, entityManager);
		this.domainClass = domainClass;
		this.entityManager = entityManager;
	}
	
	@Override
	public boolean support(String modelType) {
		// TODO Auto-generated method stub
		return domainClass.getName().equals(modelType);
	}
	
	@Override
	@Transactional //事务注解
	public void saveEntity(T entity) {
		EncryptUtil.encrypt(entity);
		
		// innerSave(entity);
		entityManager.persist(entity);
		entityManager.flush();
	}
	
	 /** 
     * 保存对象 
     * @param item 保存对象 
     * @return 
     */  
    @SuppressWarnings("unused")
	private Serializable innerSave(Object item) {  
        try {  
            if(item==null)return null;  
            Class<?> clazz = item.getClass();  
            Field idField = ReflectUtil.getIdField(clazz);  
            Method getMethod = null;  
            if(idField!=null){  
                Class<?> type = idField.getType();  
                Object val = idField.get(item);  
                if(type == String.class && (val==null || "".equals(val))){  
                    idField.set(item, UUIDUtil.uuid());  
                }  
            }else{  
                Method[] methods = clazz.getDeclaredMethods();  
                for (Method method : methods) {  
                    Id id = method.getAnnotation(Id.class);  
                    if (id != null) {  
                        Object val = method.invoke(item);  
                        if(val==null || "".equals(val)){  
                            String methodName = "s" + method.getName().substring(1);  
                            Method setMethod = clazz.getDeclaredMethod(methodName, method.getReturnType());  
                            if(setMethod!=null){  
                                setMethod.invoke(item, UUIDUtil.uuid());  
                            }  
                        }  
                        getMethod = method;  
                        break;  
                    }  
                }  
            }  
            entityManager.persist(item);  
            entityManager.flush();  
            if(idField!=null){  
                return (Serializable) idField.get(item);      
            }  
            if(getMethod!=null){  
                return (Serializable)getMethod.invoke(item);  
            }  
            return null;  
        } catch (Exception e) {  
            e.printStackTrace();  
            throw new RuntimeException(e);  
        }   
    }  
	
	@Override
	@Transactional //事务注解
	public void updateEntity(T entity) {
		saveEntity(entity); 
	}

	/** 
	 * @author Administrator
	 * @date 2017-4-20
	 * @param id
	 * @return
	 * @Description TODO(这里用一句话描述这个方法的作用)
	 * @see org.springframework.data.jpa.repository.support.SimpleJpaRepository#findOne(java.io.Serializable)
	 */
	@Override
	public T findOne(ID id) {
		T val = super.findOne(id);
		if (val != null) {
			EncryptUtil.decrypt(val);
		}
		return val;
	}

	/** 
	 * @author Administrator
	 * @date 2017-4-20
	 * @return
	 * @Description TODO(这里用一句话描述这个方法的作用)
	 * @see org.springframework.data.jpa.repository.support.SimpleJpaRepository#findAll()
	 */
	@Override
	public List<T> findAll() {
		List<T> list = super.findAll();
		for (Object val : list) {
			EncryptUtil.decrypt(val);
		}
		return list;
	}
}
